import {_decorator, clamp, Component, lerp, Node, Quat, tween, Tween, Vec3} from 'cc';
import {AudioManager} from "db://assets/scripts/common/AudioManager";
import {Utils} from "db://assets/scripts/utils/Utils";
import {GameManager} from "db://assets/scripts/game/GameManager";
import {ResourceUtils} from "db://assets/scripts/common/ResourceUtils";
import {PoolManager} from "db://assets/scripts/common/PoolManager";
import {EventManager} from "db://assets/scripts/common/EventManager";
import {EffectManager} from "db://assets/scripts/common/EffectManager";
import {RewardType} from "db://assets/scripts/game/RewardType";
import {EventType} from "db://assets/scripts/common/EventType";
import {AudioPaths} from "db://assets/scripts/common/AudioPaths";

const {ccclass, property} = _decorator;

/**
 * 奖品(奖励)脚本：金币和爱心
 */
@ccclass('RewardController')
export class RewardController extends Component {
    /**
     * 奖励类型
     */
    @property({displayOrder: 1})
    public rewardType: RewardType = RewardType.GOLD;
    /**
     * 是否已经落在地上
     */
    public isDropOver: boolean = false;

    /**
     * 拖尾缩放
     */
    private trialScale = new Vec3(3, 3, 3);
    /**
     * 拖尾位置
     */
    private trialPos: Vec3 = new Vec3(0, -0.1, 0);
    /**
     * tween
     */
    private tweenBounce: Tween<Node>;
    /**
     * 旋转
     */
    private currentQuat: Quat = new Quat();
    /**
     * 是否自动旋转
     */
    private isAutoRotate: boolean = false;
    /**
     * 是否正在吸入中
     */
    private isInhaling: boolean = false;
    /**
     * 原始缩放大小
     */
    private originScale: Vec3;
    /**
     * 父亲节点
     */
    private parentNode: Node;
    /**
     * 拖尾节点
     */
    private trialNode: Node;
    /**
     * 最终目标位置
     */
    private endTargetPosition: Vec3 = new Vec3();
    /**
     * 中间位置
     */
    private midTargetPosition: Vec3 = new Vec3();
    /**
     * 下一次的位置
     */
    private stepTargetPosition: Vec3 = new Vec3();
    /**
     * 上升最大速度
     */
    private upSpeedY: number = 0.2;
    /**
     * 下降最大速度
     */
    private downSpeedY: number = 0.2;
    /**
     * 当前速度
     */
    private currentSpeedY: number = 0;
    /**
     * 初始奖品世界坐标
     */
    private originWorldPosition: Vec3 = new Vec3();
    /**
     * 已经到达中间位置
     */
    private isArriveMinPosition: boolean = false;
    /**
     * 当前奖品世界坐标
     */
    private rewardWorldPosition: Vec3 = new Vec3();
    /**
     * 目标(主角)位置
     */
    private playerWorldPosition: Vec3 = new Vec3();
    /**
     * 下一个位置
     */
    private nextWorldPosition: Vec3 = new Vec3();
    /**
     * 奖品和玩家之间的向量差
     */
    private offsetPosition: Vec3 = new Vec3();
    /**
     * 目标时间坐标
     */
    private targetWorldPosition: Vec3 = new Vec3();
    /**
     * 奖品总飞行时间
     */
    private totalFlyTime: number = 0;
    /**
     * 奖品当前飞行时间
     */
    private currentFlyTime: number = 0;
    /**
     * 提升时间
     */
    private raiseTimes: number = 1;
    /**
     * 回收缓动高度
     */
    private bouncePosition: Vec3 = new Vec3(0, 0.618, 0);
    /**
     * 回收缓动缩放
     */
    private bounceScale: Vec3 = new Vec3(0.2, 0.2, 0.2);

    onEnable() {
        EventManager.on(EventType.INHALE_REWARD, this.inhaleReward, this);
    }

    onDisable() {
        EventManager.off(EventType.INHALE_REWARD, this.inhaleReward, this);
    }

    start() {

    }

    update(deltaTime: number) {
        //奖品上下弹跳
        if (!this.isDropOver) {
            this.rewardWorldPosition.set(this.node.position);
            //先抬高
            if (!this.isArriveMinPosition) {
                this.stepTargetPosition = this.rewardWorldPosition.lerp(this.midTargetPosition, 0.03);
                this.currentSpeedY = lerp(this.upSpeedY, this.currentSpeedY, 0.03);
                this.nextWorldPosition = this.nextWorldPosition.set(this.stepTargetPosition).add3f(0, this.currentSpeedY, 0);
                this.nextWorldPosition.y = clamp(this.nextWorldPosition.y, 0, this.midTargetPosition.y);
                this.node.setPosition(this.nextWorldPosition);

                // if (pos.equals(this.midTargetPosition, 0.2)) {
                if (this.nextWorldPosition.y >= this.midTargetPosition.y) {
                    this.isArriveMinPosition = true;
                    this.currentSpeedY = 0;
                    // console.log("到达中间位置");
                }
            } else {//后降落
                this.stepTargetPosition = this.rewardWorldPosition.lerp(this.endTargetPosition, 0.02);
                this.currentSpeedY = lerp(this.downSpeedY, this.currentSpeedY, 0.05);
                // console.log("upSpeedY", this.currentSpeedY);
                this.nextWorldPosition = this.nextWorldPosition.set(this.stepTargetPosition).add3f(0, -this.currentSpeedY, 0);
                this.nextWorldPosition.y = clamp(this.nextWorldPosition.y, this.endTargetPosition.y, this.midTargetPosition.y);
                this.node.setPosition(this.nextWorldPosition);

                if (this.nextWorldPosition.equals(this.endTargetPosition, 0.3)) {
                    this.isDropOver = true;
                    // console.log("到达地板上");
                    this.isAutoRotate = true;
                    this._checkMonsterClearOver();
                }
            }
        }

        //奖品落地后自动旋转
        if (this.isAutoRotate) {
            Quat.fromEuler(this.currentQuat, 0, 120 * deltaTime, 0);
            this.node.rotate(this.currentQuat);
        }

        //奖品被玩家吸入
        if (this.isInhaling) {
            //位置靠近玩家
            this.playerWorldPosition.set(GameManager.getInstance().gamePlayerProxy.getPlayerController().node.worldPosition);
            this.rewardWorldPosition.set(this.node.worldPosition);
            //向量差
            Vec3.subtract(this.offsetPosition, this.playerWorldPosition, this.rewardWorldPosition);

            if (!this.totalFlyTime) {
                this.totalFlyTime = this.offsetPosition.length() / 2;
            }

            // 由慢到快
            this.raiseTimes += deltaTime;
            let offset = Math.pow(this.raiseTimes, 0.5) - 1;
            this.currentFlyTime += deltaTime + offset;
            this.currentFlyTime = this.currentFlyTime >= this.totalFlyTime ? this.totalFlyTime : this.currentFlyTime;

            let percent = Number((this.currentFlyTime / this.totalFlyTime).toFixed(2));
            // console.log("percent", percent);

            this.targetWorldPosition.set(this.rewardWorldPosition.x + this.offsetPosition.x * percent, this.playerWorldPosition.y, this.rewardWorldPosition.z + this.offsetPosition.z * percent);
            this.node.setWorldPosition(this.targetWorldPosition);

            let length = Utils.getTwoPositionXZLength(this.targetWorldPosition.x, this.targetWorldPosition.z, this.playerWorldPosition.x, this.playerWorldPosition.z);
            // if (this.targetWorldPosition.equals(this.playerWorldPosition, 0.1)) {
            if (length <= 0.1) {
                this.isInhaling = false;
                this.trialNode.active = false;
                PoolManager.getInstance().putNode(this.node);

                if (this.rewardType === RewardType.GOLD) {
                    GameManager.getInstance().gameGoldProxy.addGold();
                } else if (this.rewardType === RewardType.HEART) {
                    //回复5%的血量
                    let bloodNum = GameManager.getInstance().gamePlayerProxy.getPlayerController().curHpLimit * 0.05;
                    GameManager.getInstance().gamePlayerProxy.getPlayerController().addBlood(bloodNum);
                }

                this.checkInhaleOver();
                // console.log("吸收奖品");
            }
        }
    }

    /**
     * 初始化奖励信息
     *
     * @param time 时间
     * @param parentNode 父节点
     */
    init(time: number, parentNode: Node) {
        this.parentNode = parentNode;

        if (this.originScale) {
            this.node.setScale(this.originScale);
        } else {
            this.originScale = this.node.getScale();
        }

        this.isAutoRotate = false;
        this.isInhaling = false;
        this.currentSpeedY = this.upSpeedY;
        this.originWorldPosition.set(this.node.getWorldPosition().x, 1.65, this.node.getWorldPosition().z);
        this.isArriveMinPosition = false;
        this.isDropOver = false;
        this.totalFlyTime = 0;
        this.currentFlyTime = 0;
        this.raiseTimes = 1;

        //依次弹出奖品
        this.scheduleOnce(() => {
            this.show();
        }, time)

        if (!this.trialNode) {
            ResourceUtils.loadEffect("trail/coinTrail").then((pf: any) => {
                this.trialNode = PoolManager.getInstance().getNode(pf, this.node);
                this.trialNode.active = false;
                this.trialNode.setScale(this.trialScale);
                this.trialNode.setPosition(this.trialPos);
            });
        } else {
            this.trialNode.active = false;
        }
    }

    /**
     * 显示奖励
     */
    show() {
        this.node.active = true;
        let x = Math.random() * 6 - 3;//-3~3
        let y = 4;//最高的高度4~4.5;
        let z = Math.random() * 6 - 3;//-3~3
        this.endTargetPosition = this.endTargetPosition.set(this.originWorldPosition).add3f(x, 0, z);
        this.midTargetPosition = this.midTargetPosition.set(this.originWorldPosition).add3f(x / 2, y, z / 2);

        // console.log("终点位置", this.endTargetPosition, "中间位置", this.midTargetPosition);

        AudioManager.getInstance().playSound(AudioPaths.goldDropSound);
    }

    /**
     * 检查所有怪物是否已经击败，且奖品是否都全部掉落完毕
     *
     * @see RewardController
     */
    protected _checkMonsterClearOver() {
        let ndTarget = GameManager.getInstance().gameGetMonsterProxy.getNearestMonster();

        if (!ndTarget) {
            let arrReward = this.parentNode.children.filter((ndChild: Node) => {
                return ndChild.name === "gold" || ndChild.name === "heart";
            })

            let isAllDropOver = arrReward.every((ndReward: Node) => {
                let rewardController = ndReward.getComponent(RewardController);
                return rewardController.isDropOver === true;
            });

            if (isAllDropOver) {
                console.log("###所有的奖品都已经掉落到地上了");
                EventManager.dispatchEvent(EventType.INHALE_REWARD);
            }
        }
    }

    /**
     * 玩家吸入奖品
     *
     * @see RewardController
     */
    protected inhaleReward() {
        //先弹跳
        this.closeTween();
        this.tweenBounce = tween(this.node)
            .by(0.3, {position: this.bouncePosition, scale: this.bounceScale}, {easing: "bounceInOut"})
            .call(() => {
                //播放粒子特效，不要勾选粒子的prewarm属性，免得出现概率性没有播放拖尾
                this.trialNode.active = true;

                EffectManager.getInstance().playParticle(this.trialNode);

                //再吸入
                this.isInhaling = true;

            })
            .start()
    }

    /**
     * 关闭缓动
     */
    protected closeTween() {
        if (this.tweenBounce) {
            this.tweenBounce.stop();
            this.tweenBounce = null!;
        }
    }

    /**
     *  检查所有奖品是否吸收完毕
     *
     * @see RewardController
     */
    protected checkInhaleOver() {
        let arrReward = this.parentNode.children.filter((ndChild: Node) => {
            return ndChild.name === "gold" || ndChild.name === "heart";
        })

        if (!arrReward.length) {
            console.log("###已吸入全部奖品");
            AudioManager.getInstance().playSound(AudioPaths.goldCollectSound);
            EventManager.dispatchEvent(EventType.SHOW_WARP_GATE);
        }
    }
}

